﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HobSoft.SoccerBet2014.Wcf
{
    using Common.Errors;
    using Domain.ClientService;
    using Domain.DataService;
    using Domain.Factory;
    using Domain.Models;
    using Domain.Models.BfRaw;

    public class BfRequestProxyService : IBfRequestService
    {
        private readonly IBfManagerFactory bfManagerServiceFactory;
        private readonly ConcurrentDictionary<string, IBfManagerService> bfManagerServices = new ConcurrentDictionary<string, IBfManagerService>();
        public BfRequestProxyService(IBfManagerFactory bfManagerFactory)
        {
            bfManagerServiceFactory = bfManagerFactory;
        }

        public async Task<bool> Singup(BFAccount account, string certificateFile)
        {
            if (bfManagerServices.ContainsKey(account.Account))
            {
                var exiter = bfManagerServices[account.Account];
                var span = DateTime.Now - exiter.LoginInfo.LastRequestTime;
                if (exiter.LoginInfo.IsLogin && (!span.HasValue || span.Value.TotalHours < 1)) return true;
                return await bfManagerServices[account.Account].Signup(certificateFile);
            }
            var manager = bfManagerServiceFactory.CreateOrGet(account);
            bfManagerServices.TryAdd(account.Account, manager);
            return await manager.Signup(certificateFile);
        }

        public async Task<IList<MarketBook>> GetMarketBook(params string[] marketIds)
        {
            marketIds.IsNull().ThrowNull("marketIds", "need marketIds");
            var managers = bfManagerServices.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();

            if (!marketIds.Any()) return null;

            return await manager.ListMarketBook(marketIds);
        }

        public async Task<PlaceExecutionReport> Betting(string _marketId, PlaceInstruction _placeInstruction, string _customerRef)
        {
            var managers = bfManagerServices.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();
            return await manager.Betting(_marketId, _placeInstruction, _customerRef);
        }

        public async Task<CancelExecutionReport> CancelOrder(string _marketId, CancelInstruction _instruction, string _customerRef)
        {
            var managers = bfManagerServices.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();
            return await manager.CancelOrders(_marketId, _instruction, _customerRef);
        }

        public async Task<CurrentOrderSummaryReport> GetOrders()
        {
            var managers = bfManagerServices.Values.Where(m => m.LoginInfo.IsLogin);
            if (!managers.Any()) return null;
            var manager = managers.OrderByDescending(m => m.LoginInfo.LastRequestTime).FirstOrDefault();
            return await manager.ListOrders();
        }

        public async Task<BFEvent> GetEventMarkets(int eventId)
        {
            throw new NotImplementedException();
        }

        public async Task<IList<BFEvent>> GetEventByMarket(string[] marketIds)
        {
            throw new NotImplementedException();
        }

        public async Task<bool> HasLogin()
        {
            return bfManagerServices.Values.Any(m => m.LoginInfo.IsLogin);
        }
    }
}
